/* $RCSFile: Paging.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/Paging.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Globalization;

using AddonNice.Diagnostics;
using AddonNice.Settings;

using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;


namespace AddonNice.UI.WebControls
{
    /// <summary>
    /// Paging class, Addon Nice special edition
    /// </summary>
	[
	DefaultProperty("PageNumber"),
	ToolboxData("<{0}:Paging runat=server></{0}:Paging>"),
	Designer("AddonNice.UI.Design.PagingDesigner")
	]
	public class Paging : CompositeControl, IPaging
    {
        #region controls

        /// Page number
		protected WebControl tbPageNumber;

		/// Total page count
		protected Label lblPageCount;

		/// Label containg text 'of'
		protected Label lblof;

		/// Buttons
		protected Button btnFirst;
		protected Button btnPrev;
		protected Button btnNext;
		protected Button btnLast;

        #endregion controls


        #region variables to manage state

        int _CellPadding =   0;
        public int CellPadding
        {
			get
			{
                return _CellPadding;
            }
			set
			{
                _CellPadding = value;
            }
		}
        
        int _CellSpacing =   0;
        public int CellSpacing
        {
			get
			{
                return _CellSpacing;
            }
			set
			{
                _CellSpacing = value;
            }
		}

        bool _UseSkins  =   false;
        public bool UseSkins
        {
			get
			{
                return _UseSkins;
            }
			set
			{
                _UseSkins = value;
            }
		}


        /// <summary>
		/// Number of records per page
		/// </summary>
		public int RecordsPerPage
		{
			get
			{
                if (DesignMode )
                    return 10;
                object ob  =   ViewState["recordsPerPage"];
                if ( ob == null )
                    ob  =   ViewState["recordsPerPage"] =   10;
                return (int)ob;
            }
			set
			{
                ViewState["recordsPerPage"] = value;
            }
		}

        //public bool _useRad =   true;

        public bool useRad
        {
            get
            {
                if ( DesignMode )
                    return true;
                return Config.UseRadControlsForSettings;
            }
        }
        
        
        /// <summary>
		/// Hide when on single page hides controls when 
		/// there is only one page
		/// </summary>
		public bool HideOnSinglePage
		{
			get 
			{
                if (DesignMode )
                    return false;
                object ob  =   ViewState["HideOnSinglePage"];
                if ( ob == null )
                    ob  =   ViewState["HideOnSinglePage"] =   true;
                return (bool)ob;
			}
			set
			{
				ViewState["HideOnSinglePage"] = value;
			}        
		}

		/// <summary>
		/// Current page number
		/// </summary>
		public virtual int PageNumber
		{
			get 
			{
                object ob  =   ViewState["PageNumber"];
                if (ob == null)
                {
                    ob = ViewState["PageNumber"] = 1;
                }
                return (int)ob;
			}
			set
			{
                EnsureChildControls();
                if ( useRad )
                     ((RadNumericTextBox)tbPageNumber).Value    =   value;
                else ((TextBox)tbPageNumber).Text               =   value.ToString();
    			ViewState["PageNumber"]                         =   value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether validation is performed when the control buttons are clicked.
		/// </summary>
		[
		Description("Gets or sets a value indicating whether validation is performed when the control buttons are clicked.")
		] 
		public bool CausesValidation
		{
			get
			{
                object ob  =   ViewState["CausesValidation"];
                if ( ob == null )
                    ob  =   ViewState["CausesValidation"] =   true;
                return (bool)ob;
			}
			set
			{
				ViewState["CausesValidation"] = value;       
			}
		}

		/// <summary>
		/// Total Record Count
		/// </summary>
		public int RecordCount
		{
			get 
			{
                if ( DesignMode )
                    return 20;
				object ob         =  ViewState["RecordCount"];
			    if ( ob == null)
				    ob  =   ViewState["RecordCount"]    =   1;
				return (int)ob;
			}
			set
			{
				object ob         =  ViewState["RecordCount"];
                int oldVal        = -1;
			    if ( ob != null)
                    oldVal        = (int)ob;
                if (oldVal != value)
                {
                    ViewState["RecordCount"] = value;
                    RefreshButtons();
                }
			}
		}

		/// <summary>
		/// Total pages count
		/// </summary>
		public int PageCount
		{
			get 
			{
				// Calculate page count
				int _PageCount = RecordCount / RecordsPerPage;

				// adjust for spillover
				if ( RecordCount % RecordsPerPage > 0)
					_PageCount++;

				if (_PageCount < 1)
					_PageCount = 1;

				return _PageCount;
			}
		}
        #endregion variables to manage state

        #region events and handlers

        /// Move event raised when a move is performed
		public event EventHandler OnMove;

        /// <summary>
		/// Used by OnMove event
		/// </summary>
		protected virtual void OnMoveHandler(EventArgs e)
		{
			if (OnMove != null)
			{
				OnMove(this, e);
			}
		}

			
        /// <summary>
        /// Checks pagenumber value and raises the event OnMove
        /// </summary>
	    protected void NavigationButtonClick(Object sender, EventArgs e)
		{
            int oldPageNumber   =   PageNumber;
			// get the command
			string arg          =   ((Button)sender).CommandArgument;
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Paging NavigationButtonClick arg: {0}.",arg),WebControlsTraceSwitch.Sw.Info);
			// do the command
			switch(arg)
			{
				case "next":
					if (PageNumber < PageCount)
						PageNumber++;
					break;
				case "prev":
					if (PageNumber > 1)
						PageNumber--;
					break;
				case "last":
					PageNumber = PageCount;
					break;
				case "first":
					PageNumber = 1;
					break;
			}

            // only raise event when necessary
            if (PageNumber != oldPageNumber)
            {
                RefreshButtons();
                OnMoveHandler(new EventArgs());
            }
		}

        /// <summary>
        /// Checks pagenumber value and raises the event OnMove
        /// </summary>
        protected void Paging_TextChanged(object sender, EventArgs e)
        {
            int oldPageNumber   =   PageNumber;
			int _PageNumber     =   0;
            if ( useRad )
                _PageNumber = (int)((RadNumericTextBox)tbPageNumber).Value.Value;
            else
            {
                _PageNumber = Convert.ToInt32(((TextBox)tbPageNumber).Text);
            } 
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Paging Paging_TextChanged _PageNumber: {0}.",_PageNumber),WebControlsTraceSwitch.Sw.Info);

			if (_PageNumber > PageCount)
			{
				PageNumber = PageCount;
			}
			else if (_PageNumber < 1)
			{
				PageNumber = 1;
			}
			else
			{
				PageNumber = _PageNumber;
			}
            // only raise event when necessary
            if (PageNumber != oldPageNumber)
            {
                RefreshButtons();
                //Raise the event OnMove
                OnMoveHandler(new EventArgs());
            }
		}
        
        #endregion events and handlers
		/// <summary>
		/// Enable/disable the nav controls based on the current context, update labels
		/// </summary>
		protected virtual void RefreshButtons()
		{
            EnsureChildControls();
			// enable/disable the nav controls based on the current context
			// we should only show the first button if we're NOT on the first page already
			btnFirst.Enabled            =   (PageNumber != 1);
			btnPrev.Enabled             =   (PageNumber > 1);
			btnNext.Enabled             =   (PageNumber < PageCount);
			btnLast.Enabled             =   (PageNumber != PageCount);

			//Update labels
			lblPageCount.Text           =   PageCount.ToString();
            // Don't display when flag set or no records
			if ( PageCount <= 1 && ( HideOnSinglePage || RecordCount == 0 ))
			{
                Visible                 =   false;
                if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                    Trace2.WriteLine( "[V]Paging RefreshButtons Visible=false.",WebControlsTraceSwitch.Sw.Info);
			}
			else
			{
                Visible                 =   true;
				btnFirst.Visible        =   true;
				btnPrev.Visible         =   true;
				btnNext.Visible         =   true;
				btnLast.Visible         =   true;
				lblof.Visible           =   true;
				lblPageCount.Visible    =   true;
				tbPageNumber.Visible    =   true;
			}
		}

		void Page_Load(object sender, System.EventArgs e)
		{
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging OnLoad BEG.",WebControlsTraceSwitch.Sw.Info);
			RefreshButtons();
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging OnLoad END.",WebControlsTraceSwitch.Sw.Info);
        }

        #region ctor
        /// <summary>
		/// Main class managing pages
		/// </summary>
		public Paging()
		{
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging Ctor called.",WebControlsTraceSwitch.Sw.Info);
        }
        #endregion ctor


        //Construct controls
        protected override void CreateChildControls()
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging CreateChildControls BEG.",WebControlsTraceSwitch.Sw.Info);
            Controls.Clear();
            CreateNextPrev();
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging CreateChildControls END.",WebControlsTraceSwitch.Sw.Info);
        }
        
        protected virtual void CreateNextPrev()
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging CreateNextPrev BEG.",WebControlsTraceSwitch.Sw.Info);
			btnFirst                    =   new Button();
            btnFirst.ID                 =   "Pager_BtnFirst";
            if ( UseSkins )
                btnFirst.SkinID         =   "PagerFirst";
			btnFirst.Font.Bold          =   true;
			btnFirst.Text               =   " |< ";
			btnFirst.CommandArgument    =   "first";
			Controls.Add(btnFirst);

			btnPrev                     =   new Button();
            btnPrev.ID                  =   "Pager_BtnPrev";
            if ( UseSkins )
                btnPrev.SkinID          =   "PagerPrev";
			btnPrev.Font.Bold           =   true;
			btnPrev.Text                =   " < ";
			btnPrev.CommandArgument     =   "prev";
			Controls.Add(btnPrev);
            
            
            if (useRad)
            {
                RadNumericTextBox tbPage            =   new RadNumericTextBox();
                tbPage.ShowSpinButtons              =   true;
                tbPage.MinValue                     =   0;
                tbPage.Type                         =   NumericType.Number;
                tbPage.AutoPostBack                 =   true;
                tbPage.NumberFormat.DecimalDigits   =   0;
                tbPage.Value                        =   PageNumber;
                tbPageNumber                        =   tbPage;
            }
            else
            {
                TextBox tbPage                      =   new TextBox();
                tbPage.AutoPostBack                 =   true;
                tbPage.Text                         =   PageNumber.ToString();
                tbPageNumber                        =   tbPage;
            }
            tbPageNumber.ID                         =   "Pager_PageNbr";
			tbPageNumber.Width                      =   new Unit("40px");
			tbPageNumber.EnableViewState            =   true;

		    Controls.Add(tbPageNumber);


			btnNext                         =   new Button();
            btnNext.ID                      =   "Pager_BtnNext";
            if ( UseSkins )
                btnNext.SkinID              =   "PagerNext";
			btnNext.Font.Bold               =   true;
			btnNext.Text                    =   " > ";
			btnNext.CommandArgument         =   "next";
			Controls.Add(btnNext);

			btnLast                         =   new Button();
            btnLast.ID                      =   "Pager_BtnLast";
            if ( UseSkins )
                btnLast.SkinID              =   "PagerLast";
			btnLast.Font.Bold               =   true;
			btnLast.Text                    =   " >| ";
			btnLast.CommandArgument         =   "last";
			Controls.Add(btnLast);

			lblof                           =   new Label();
            lblof.ID                        =   "Pager_lblof";
			lblof.EnableViewState           =   false;
			lblof.Text                      =   "&#160;/&#160;";
			Controls.Add(lblof);

			lblPageCount                    =   new Label();
            lblPageCount.ID                 =   "Pager_lbPgCnt";
			lblPageCount.EnableViewState    =   false;
			Controls.Add(lblPageCount);
            
			//Add handlers
            if ( useRad )
			    ((RadNumericTextBox)tbPageNumber).TextChanged   +=  new EventHandler(Paging_TextChanged);
			else ((TextBox)tbPageNumber).TextChanged            +=  new EventHandler(Paging_TextChanged);
			btnFirst.Click              +=  new System.EventHandler(NavigationButtonClick);
			btnPrev.Click               +=  new System.EventHandler(NavigationButtonClick);
			btnNext.Click               +=  new System.EventHandler(NavigationButtonClick);
			btnLast.Click               +=  new System.EventHandler(NavigationButtonClick);

            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging CreateNextPrev END.",WebControlsTraceSwitch.Sw.Info);
		}

        protected override void OnInit(EventArgs e)
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging OnInit BEG.",WebControlsTraceSwitch.Sw.Info);
			Load                        +=  new System.EventHandler(Page_Load);
            base.OnInit(e);
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging OnInit END.",WebControlsTraceSwitch.Sw.Info);
        }


        protected override void RenderContents(HtmlTextWriter writer)
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging RenderContents BEG.",WebControlsTraceSwitch.Sw.Info);
            try
            {
                AddAttributesToRender(writer);

                writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, CellPadding.ToString(), false);
                writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, CellSpacing.ToString(), false);
                writer.RenderBeginTag(HtmlTextWriterTag.Table);
                writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                RenderPrevNext(writer);
                writer.RenderEndTag();
                writer.RenderEndTag();
            }
            catch (Exception ex)
            {
                if ( WebControlsTraceSwitch.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Paging RenderContents ex: {0}",ex),WebControlsTraceSwitch.Sw.Info);
                throw;
            }
             if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging RenderContents END.",WebControlsTraceSwitch.Sw.Info);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging Render BEG.",WebControlsTraceSwitch.Sw.Info);
            if ( DesignMode )
                EnsureChildControls();
            try
            {
                base.Render(writer);
            }
            catch (Exception ex)
            {
                if ( WebControlsTraceSwitch.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Paging Render ex: {0}",ex),WebControlsTraceSwitch.Sw.Info);
                throw;
            }
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging Render END.",WebControlsTraceSwitch.Sw.Info);
        }

        protected void RenderPrevNext(HtmlTextWriter writer)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnFirst.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnPrev.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            tbPageNumber.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnNext.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnLast.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            lblof.RenderControl(writer);
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            lblPageCount.RenderControl(writer);
            writer.RenderEndTag();
        }
	}
}